package goDaemo

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"os/signal"
	"strconv"
	"syscall"
	"time"
)

const (
	//socketFile = "/tmp/daemon.sock"
	stopFile = "/tmp/stop_daemon"
)

var daemonPID int

func main() {
	fmt.Println("程序开始运行...")

	if len(os.Args) > 1 {
		switch os.Args[1] {
		case "start":
			startDaemon()
			return
		case "stop":
			stopDaemon()
			return
		case "fork":
			forkChildProcess()
			return
		case "list":
			listProcesses()
			return
		}
	}

	log.Println("请使用 'start'、'stop'、'fork' 或 'list' 参数来启动、停止、创建子进程或列出进程。")
}

// startDaemon 启动守护进程
func startDaemon() {
	if _, err := os.Stat(socketFile); !os.IsNotExist(err) {
		log.Println("守护进程已经在运行。")
		return
	}

	// 启动当前程序本身，传递 "run" 参数
	proc, err := os.StartProcess(os.Args[0], []string{os.Args[0], "run"}, &os.ProcAttr{})
	if err != nil {
		log.Fatal("启动守护进程失败:", err)
	}

	// 记录守护进程的 PID
	daemonPID = proc.Pid

	if err := os.WriteFile(socketFile, []byte("running"), 0644); err != nil {
		log.Fatal("创建 socket 文件失败:", err)
	}

	log.Println("守护进程已启动，PID:", daemonPID)
}

// forkChildProcess 创建子进程并授权
func forkChildProcess() {
	pid, err := syscall.ForkExec(os.Args[0], []string{os.Args[0], "run"}, &syscall.ProcAttr{
		Sys: &syscall.SysProcAttr{
			Setpgid: true,
		},
	})
	if err != nil {
		log.Fatal("创建子进程失败:", err)
	}

	log.Println("子进程已创建，PID:", pid)
}

// listProcesses 列出当前的父进程和子进程
func listProcesses() {
	// 使用守护进程的 PID
	fmt.Printf("守护进程ID: %d\n", daemonPID)

	// 列出子进程
	fmt.Println("子进程:")
	cmd := exec.Command("pgrep", "-P", strconv.Itoa(daemonPID))
	output, err := cmd.Output()
	if err != nil {
		log.Fatalf("获取子进程失败: %v", err)
	}

	children := string(output)
	if children == "" {
		fmt.Println("没有找到子进程.")
	} else {
		fmt.Println(children)
	}
}

// run 处理守护进程的逻辑
func run() {
	log.Println("我是守护进程:", os.Getpid())
	go handleSignals()
	monitorStopSignal()
	log.Println("守护进程结束:", os.Getpid())
}

// stopDaemon 用于停止守护进程
func stopDaemon() {
	if err := os.WriteFile(stopFile, []byte("stop"), 0644); err != nil {
		log.Fatalf("创建停止文件失败: %v", err)
	}
	log.Println("守护进程已请求停止")
	os.Remove(socketFile)
}

// handleSignals 处理停止信号
func handleSignals() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGTERM)

	<-c // 等待停止信号
	log.Println("收到停止信号，正在退出...")
	os.Remove(socketFile)
	os.Exit(0)
}

// monitorStopSignal 监控停止信号
func monitorStopSignal() {
	for {
		if _, err := os.Stat(stopFile); os.IsNotExist(err) {
			time.Sleep(1 * time.Second) // 每秒检查一次
			continue
		}
		log.Println("收到停止信号，正在退出...")
		os.Remove(stopFile)
		return
	}
}

// main 函数的入口，处理 "run" 参数
func init() {
	if len(os.Args) > 1 && os.Args[1] == "run" {
		run() // 调用 run 函数
		os.Exit(0)
	}
}
